package ejercicio3EncarpetadoTransportes.servidores;

import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;

import ejercicio3EncarpetadoTransportes.clientes.estaciones.Estaciones;
import ejercicio3EncarpetadoTransportes.clientes.transportes.Transportes;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta02Directo;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta02porA;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta02porB;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta03Directo;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta03porA;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde01Hasta03porB;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde02Hasta03Directo;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde02Hasta03porA;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde02Hasta03porB;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde03Hasta04Directo;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde03Hasta04porA;
import ejercicio3EncarpetadoTransportes.servidores.rutas.Desde03Hasta04porB;
import ejercicio3EncarpetadoTransportes.servidores.rutas.RutaAsignada;



public class ServidorDeRutas implements Observer{
	ArrayList<Estaciones>estaciones;
	ArrayList<Transportes>transportesEnMovimiento;
	
	public ServidorDeRutas() {
		this.estaciones=inicializaEstaciones();
		this.transportesEnMovimiento=null;
	}

	
	private ArrayList<Estaciones> inicializaEstaciones() {
		ArrayList<Estaciones>estaciones=new ArrayList<Estaciones>();
		for(int i=1;i<9;i++)
			estaciones.add(new Estaciones(i));
		return estaciones;
	}


	/**Activa parada en el movil mas cercano
	 * */
	public boolean servirAEstacioConPrioridad(){
		Estaciones estacion=null;
		int i;
		for(i=0;i<estaciones.size();i++)
			if (estaciones.get(i).isPriopr())
				estacion=estaciones.get(i);
		if(estacion==null)return false;
		if(this.activaEstacionado(i)){
			estacion.setPasajeros(this.transportesEnMovimiento.get(this.transportesEnMovimiento.size()
					).setLugaresLibres(estacion.getPasajeros()));
			return true;
		}
		else{
			int dde=estacion.getId();
			while(dde>0){
				for(int j=0;j<transportesEnMovimiento.size();){
					if (dde==transportesEnMovimiento.get(j).getPoxima()){
						transportesEnMovimiento.get(j).setRutAsignada(
								this.ObtenerRutaDeAB(dde,estacion.getDestino()));
						estacion.setPasajeros(this.transportesEnMovimiento.get(j)
								.setLugaresLibres(estacion.getPasajeros()));
						return true;
					}
				}
			dde--;
			}
		}
		return false;
	}
	
	/**Activa parada en el movil mas cercano a la estacion actual segun la cantidad de pasajeros en el transporte
	 * sino busca en le estacion anterior 
	 * */
	public boolean servirAEstacion(Estaciones est){
		if(this.activaEstacionado(est.getId())){
			est.setPasajeros(this.transportesEnMovimiento.get(this.transportesEnMovimiento.size()
					).setLugaresLibres(est.getPasajeros()));
			return true;
		}
		else{
			int dde=est.getId();
			while(dde>0){
				for(int j=0;j<transportesEnMovimiento.size();j++){
					if (dde==transportesEnMovimiento.get(j).getPoxima()&&transportesEnMovimiento.get(j).getLugaresLibres()>0){
						transportesEnMovimiento.get(j).setRutAsignada(this.ObtenerRutaDeAB(dde,est.getDestino()));
						est.setPasajeros(this.transportesEnMovimiento.get(j).setLugaresLibres(est.getPasajeros()));
						return true;
					}
				}
			dde--;
			}
			return false;
		}
	}
	
	/**Activa parada en el movil verificando que no hayan transportes estacionados y luego de la forma normal
	 * */
	public boolean servirAEstacionHorasPico(Estaciones est){
		if(this.activaEstacionado(est.getId())){
			est.setPasajeros(this.transportesEnMovimiento.get(this.transportesEnMovimiento.size()
					).setLugaresLibres(est.getPasajeros()));
			return true;
		}
		else{
			int j=est.getId()-1;//desde la actual a cero
			while(j>0){
				if (this.activaEstacionado(j,est.getDestino())){
					est.setPasajeros(this.transportesEnMovimiento.get(j).setLugaresLibres(est.getPasajeros()));
					return true;
				}
				j--;
			}
			j=this.estaciones.size();//desde la ultima a la actual
			while(j>est.getId()){
				if (this.activaEstacionado(j,est.getDestino())){
					est.setPasajeros(this.transportesEnMovimiento.get(j).setLugaresLibres(est.getPasajeros()));
					return true;
				}
				j--;
			}
		}
		return this.servirAEstacion(est);
	}
	
	

	/**Elije la mejor ruta segun origen destino y cantidad de instancias
	 * */
	private RutaAsignada ObtenerRutaDeAB(int origen, int destino) {
		RutaAsignada rut = null;
		if (Desde01Hasta02Directo.desde==origen&&Desde01Hasta02Directo.hasta==destino){
			if(Desde01Hasta02Directo.instancias<RutaAsignada.MAX_TRANS_POR_RUTA)rut=new Desde01Hasta02Directo();
			else if (Desde01Hasta02porA.instanciasPorA<RutaAsignada.MAX_TRANS_POR_RUTA)rut=new Desde01Hasta02porA();
			else rut=new Desde01Hasta02porB();
		}
		else if(Desde02Hasta03Directo.desde==origen&&Desde02Hasta03Directo.hasta==destino){
			if(Desde02Hasta03Directo.instancias<RutaAsignada.MAX_TRANS_POR_RUTA)rut= new Desde02Hasta03Directo();
			else if (Desde02Hasta03porA.instanciasPorA<RutaAsignada.MAX_TRANS_POR_RUTA)rut=new Desde02Hasta03porA();
			else rut=new Desde02Hasta03porB();
		}
		else if(Desde03Hasta04Directo.desde==origen&&Desde03Hasta04Directo.hasta==destino){
			if(Desde03Hasta04Directo.instancias<RutaAsignada.MAX_TRANS_POR_RUTA)rut= new Desde03Hasta04Directo();
			else if (Desde03Hasta04porA.instanciasPorA<RutaAsignada.MAX_TRANS_POR_RUTA)rut=new Desde03Hasta04porA();
			else rut=new Desde03Hasta04porB();
		}
		else if(Desde01Hasta03Directo.desde==origen&&Desde01Hasta03Directo.hasta==destino){
			if(Desde01Hasta03Directo.instancias<RutaAsignada.MAX_TRANS_POR_RUTA)rut= new Desde01Hasta03Directo();
			else if (Desde01Hasta03porA.instanciasPorA<RutaAsignada.MAX_TRANS_POR_RUTA)rut=new Desde01Hasta03porA();
			else rut=new Desde01Hasta03porB();
		}
		return rut;
	}
	

	
	/**Activa el transporte estacionado en la estacion i con el destino y lo reporta en la lista
	 **/	
	private boolean activaEstacionado(int j, int destino) {
		Estaciones estacion = this.estaciones.get(j);
		if(estacion.getEstacionado()!=null){
			estacion.getEstacionado().setRutAsignada(
					this.ObtenerRutaDeAB(j,destino));
			transportesEnMovimiento.add(estacion.getEstacionado());
			estacion.setPasajeros(this.transportesEnMovimiento.get(this.transportesEnMovimiento.size()
					).setLugaresLibres(estacion.getPasajeros()));
			estacion.setEstacionado(null);
			return true;
			}
		else return false;
	}
	
	/**Activa el transporte estacionado en la estacion i y lo reporta en la lista
	 **/
	private boolean activaEstacionado(int i){
		Estaciones estacion = this.estaciones.get(i);
		if(estacion.getEstacionado()!=null){
			estacion.getEstacionado().setRutAsignada(
					this.ObtenerRutaDeAB(estacion.getId(),estacion.getDestino()));
			transportesEnMovimiento.add(estacion.getEstacionado());
			estacion.setPasajeros(this.transportesEnMovimiento.get(this.transportesEnMovimiento.size()
					).setLugaresLibres(estacion.getPasajeros()));
			estacion.setEstacionado(null);
			return true;
			}
		else return false;
	}

	public void update(Observable o, Object arg) {
		if (o instanceof Estaciones) {
			Estaciones estacion = (Estaciones)o;
			this.estaciones.set(estacion.getId(), estacion);
			}
		}

	
}
